﻿// jQuery's version of window.onload function
$(document).ready(function () {
    var $container = $('.canvas_container');
    if ($container.length > 0) {
        scene.init($container);
    }
});

var scene = (function ($, undefined)
{
    var _renderer = null;
    var _scene = null;
    var _camera = null;
    var _renderFunctions = [];

    /**
     * Creates the 3D scene, camera and WebGL renderer.
     * Then goes ahead and adds the renderer to the body
     */
    var init = function ($container)
    {
        // get the DOM element to attach to
        $('.loading').hide();

        var width = $container.width(),
            height = $container.height();

        // create a WebGL renderer, camera
        _renderer = new THREE.WebGLRenderer();
        _renderer.setSize(width, height); // start the renderer
        $container.append(_renderer.domElement); // attach the render-supplied DOM element

        // create a scene
        _scene = new THREE.Scene();
        
        var aspect = width / height;
        _camera = _createCamera(aspect);
        _scene.add(_camera);

        // Initialize other modules
        scene.controls.init($container, _camera, _render);
        distances.init();
        scene.mesh.init(_renderFunctions);

        scene.light.init();
        scene.light.addLightsToScene(_scene);

        scene.mesh.label.init($container, _scene);
        scene.mesh.content.init($container, _scene, _camera);

        $("#start_button").click(function () {
            _start();
        });

        window.addEventListener('resize', _onWindowResize, false);

        _animate();
    };

    var destroy = function ()
    {
        _renderer = null;
        _scene = null;
        _camera = null;
        _renderFunctions = null;
    };

    var _start = function()
    {
        $('.loading').show();
        
        _renderFunctions = [];
        scene.mesh.removeMeshesFromScene(_scene);

        // Get the actual distances between entities
        distances.get(function (actualDistances) {
            $('.object_count').text('Number of objects: ' + actualDistances.length);
            $('.loading').hide();

            // Create meshes
            var meshes = scene.mesh.addMeshesToScene(_scene, actualDistances);

            // Create springs between meshes
            scene.mesh.spring.init(_renderFunctions);
            scene.mesh.spring.createSpringsBetweenMeshes(meshes, actualDistances);
        });
    };

    var _animate = function ()
    {
        requestAnimationFrame(_animate);

        $.each(_renderFunctions, function(i, renderFunction) {
            renderFunction();
        });
        
        _render();
        scene.controls.updateControls();
        scene.mesh.label.updateLabel(_camera);
    };

    var _render = function ()
    {
        _renderer.render(_scene, _camera);
    };
    
    var _createCamera = function(aspect)
    {
        // set some camera attributes
        var cameraAngle = 45,
            nearPlane = 0.1,
            farPlane = 10000;

        var camera = new THREE.PerspectiveCamera(
            cameraAngle,
            aspect,
            nearPlane,
            farPlane);

        // the camera starts at 0,0,0
        // so pull it back
        camera.position.z = 75;

        return camera;
    };

    var _onWindowResize = function()
    {
        var $container = $('.canvas_container');

        var width = $container.width(),
            height = $container.height();

        _camera.aspect = width / height;
        _camera.updateProjectionMatrix();
        scene.controls.handleResize();

        _renderer.setSize(width, height);
        _render();
    };

    // public API
    return {
        init: init,
        destroy: destroy
    };
})(jQuery);